using System;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Collections;
using System.Drawing.Design;
using System.ComponentModel.Design;

namespace NewComboBox
{

    [ToolboxItem(true)]
    //[ToolboxBitmap(typeof(ImageComboBox), "ComboBMP.bmp")]
    [Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
    public class ImageComboBox : ComboBox
    {
        #region Constantes

        private ImageComboBoxItemCollection ListItems = null;
        private const int RECTCOLOR_LEFT = 2;
        private const int RECTCOLOR_TOP = 2;
        private const int RECTCOLOR_WIDTH = 40;
        private const int RECTTEXT_MARGIN = 2;
        private const int RECTTEXT_LEFT = RECTCOLOR_LEFT + RECTTEXT_MARGIN;

        #endregion Constantes

        #region Construction

        public ImageComboBox()
        {
            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.DropDownStyle = ComboBoxStyle.DropDownList;
            base.ItemHeight = 17;
            ListItems = new ImageComboBoxItemCollection(this);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing) { }
            base.Dispose(disposing);
        }

        #endregion Construction

        #region Propertise

        [Category("Behavior")]
        [Description("The collection of items in the ImageComboBox.")]
        [Localizable(true)]
        [MergableProperty(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [EditorAttribute(typeof(CollectionEditor), typeof(UITypeEditor))]
        [TypeConverterAttribute(typeof(ImageComboBoxItemCollection))]

        public new ImageComboBoxItemCollection Items
        {
            get
            {
                this.Imagelist = Imls;
                return this.ListItems;
            }
            set
            {
                // when the datasource property is set, it takes precedence over Items Property.
                // This is the default combobox behavior. 
                if (this.DataSource != null)
                    throw new System.Exception("The Items cannot be used concurrently with the DataSource.");
                else
                    this.ListItems = (ImageComboBoxItemCollection)value;
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public new int ItemHeight
        {
            get
            {
                return base.ItemHeight;
            }
            set
            {
                base.ItemHeight = value;
            }
        }

        ImageList Imls;
        public ImageList Imagelist
        {
            set { Imls = value; }
            get { return Imls; }
        }

        int indent = 0;
        public int Indent
        {
            set { if(value>=0)indent = value; }
            get { return indent; }
        }

        Color HighLightSelectingColor_ = Color.FromArgb(210, 225, 240);
        public Color HighLightSelectingColor
        {
            get { return HighLightSelectingColor_; }
            set { HighLightSelectingColor_ = value; }
        }


        #endregion

        #region " Event! "

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            try
            {
                Graphics Grphcs = e.Graphics;
                Color BlockColor = Color.Empty;

                if (this.Imls == null || Imls.Images.Count == 0)
                {
                    if (e.Index >= 0)
                        Grphcs.DrawString(Text, this.Items[e.Index].Font, new SolidBrush(Color.SteelBlue), new Rectangle(RECTTEXT_LEFT, e.Bounds.Top, e.Bounds.Width - RECTTEXT_LEFT, ItemHeight));
                    else
                        Grphcs.DrawString(Text, this.Font, new SolidBrush(Color.SteelBlue), new Rectangle(RECTTEXT_LEFT, e.Bounds.Top, e.Bounds.Width - RECTTEXT_LEFT, ItemHeight));
                    base.OnDrawItem(e);
                    return;
                }

                ImageComboBoxItem item = (ImageComboBoxItem)this.Items[e.Index];
                if (item.Font == null)
                    item.Font = this.Font;

                if (item.ImageIndex >= 0)
                {
                    Image theIcon = this.Imls.Images[item.ImageIndex];
                    Bitmap ImageToDraw = new Bitmap(theIcon, e.Bounds.Height , e.Bounds.Height );
                    int IconHeight = ImageToDraw.Height;
                    int IconWidth = ImageToDraw.Width;
                    //int offset = 1;

                    int left = RECTCOLOR_LEFT;

                    if ((e.State & DrawItemState.Focus) > 0)
                    {
                        Grphcs.FillRectangle(new SolidBrush(HighLightSelectingColor_), left - 3 , e.Bounds.Top + RECTCOLOR_TOP - 2, Width - 2, ItemHeight);
                        Rectangle imageRect = new Rectangle(left + 1 + item.ItemIndent, e.Bounds.Top + 1, IconWidth, IconHeight);
                        e.Graphics.DrawImage(ImageToDraw, imageRect);
                        Grphcs.DrawString(item.Text, e.Font, new SolidBrush(Color.SteelBlue), new Rectangle(RECTTEXT_LEFT + IconWidth + item.ItemIndent, e.Bounds.Top, e.Bounds.Width - RECTTEXT_LEFT, ItemHeight));
                    }
                    else
                    {
                        if (e.Index == SelectedIndex && Focused)
                        {
                            Grphcs.FillRectangle(new SolidBrush(BackColor), left - 3 , e.Bounds.Top + RECTCOLOR_TOP - 2, Width - 2, ItemHeight);
                            Grphcs.DrawString(item.Text, e.Font, new SolidBrush(ForeColor), new Rectangle(RECTTEXT_LEFT + IconWidth + item.ItemIndent, e.Bounds.Top, e.Bounds.Width - RECTTEXT_LEFT, ItemHeight));
                            Rectangle imageRect = new Rectangle(left + 1 + item.ItemIndent, e.Bounds.Top + 1, IconWidth, IconHeight);
                            e.Graphics.DrawImage(ImageToDraw, imageRect);
                        }
                        else
                        {
                            e.DrawBackground();
                            Grphcs.DrawString(item.Text, e.Font, new SolidBrush(ForeColor), new Rectangle(RECTTEXT_LEFT + IconWidth + item.ItemIndent, e.Bounds.Top, e.Bounds.Width - RECTTEXT_LEFT, ItemHeight));
                            Rectangle imageRect = new Rectangle(left + 1 + item.ItemIndent, e.Bounds.Top + 1, IconWidth, IconHeight);
                            e.Graphics.DrawImage(ImageToDraw, imageRect);
                        }
                    }
                }
            }
            catch { }
            base.OnDrawItem(e);
        }

        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            base.OnMeasureItem(e);
            if (this.DataSource != null)
            {
                return; // currently ownerdrawvariable support is implemented only for Items Collection.
            }
            if (e.Index >= 0 && this.Items.Count > 0 && e.Index < this.Items.Count)
            {
                Font itemFont = ((ImageComboBoxItem)this.Items[e.Index]).Font == null ? this.Font : ((ImageComboBoxItem)this.Items[e.Index]).Font;
                SizeF TextSize = e.Graphics.MeasureString(((ImageComboBoxItem)this.Items[e.Index]).Text, itemFont);
                e.ItemHeight = (int)TextSize.Height;
                e.ItemWidth = (int)TextSize.Width;
            }
        }

        #endregion

        #region Methods to access base class items.

        public void ComboBoxSetElement(int index, object value)
        {
            base.Items[index] = value;
        }

        public ImageComboBoxItem ComboBoxGetElement(int index)
        {
            return (ImageComboBoxItem)base.Items[index];
        }

        public IEnumerator ComboBoxGetEnumerator()
        {
            return base.Items.GetEnumerator();
        }

        public int ComboBoxGetItemCount()
        {
            return base.Items.Count;
        }

        public bool ComboBoxContains(ImageComboBoxItem item)
        {
            return base.Items.Contains(item);
        }

        public int ComboBoxInsertItem(int index, ImageComboBoxItem item)
        {
            item.Text = (item.Text.Length == 0) ? item.GetType().Name + index.ToString() : item.Text;
            base.Items.Insert(index, item);
            return index;
        }

        public int ComboBoxAddItem(ImageComboBoxItem item)
        {
            item.Text = (item.Text.Length == 0) ? item.GetType().Name + base.Items.Count.ToString() : item.Text;
            base.Items.Add(item);

            return base.Items.Count - 1;
        }

        public void ComboBoxRemoveItemAt(int index)
        {
            base.Items.RemoveAt(index);
        }
        public void ComboBoxRemoveItem(ImageComboBoxItem item)
        {
            base.Items.Remove(item);
        }
        public void ComboBoxClear()
        {
            base.Items.Clear();
        }

        #endregion

    }
}
